﻿using Acl.ComponentModel;
using Acl.Reflection;

using System;
using System.Linq;
using System.Reflection;

namespace Acl.Modular
{
    /// <summary>
    ///
    /// </summary>
    public static class ModuleExtensions
    {
        /// <summary>
        /// 启动模块管理器
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <returns></returns>
        public static void UseModular(this IServiceProvider serviceProvider)
        {
            Guard.NotNull(serviceProvider, nameof(serviceProvider));

            if (serviceProvider is IServiceRegistry services)
            {
                if (!services.IsRegistered<IModuleManager>())
                    services.AddSingleton<IModuleManager, ModuleManager>();
            }

            var moduleManager = serviceProvider.GetService<IModuleManager>();

            moduleManager.Configure();
            moduleManager.Start();
        }

        /// <summary>
        /// 从Assembly 里注册Module 和 ModuleListener
        /// </summary>
        /// <param name="services"></param>
        /// <param name="assembly"></param>
        /// <returns></returns>
        public static IServiceRegistry AddModulesFromAssembly(this IServiceRegistry services, Assembly assembly)
        {
            Guard.NotNull(services, nameof(services));
            Guard.NotNull(assembly, nameof(assembly));

            if (!services.IsRegistered<IModuleManager>())
                services.AddSingleton<IModuleManager, ModuleManager>();

            foreach (var t in assembly.GetTypes()
                       .Where(t => !t.IsAbstract)
                       .Where(t => t.IsClass)
                       .Where(t => !t.IsGenericType)
                       .Where(t => t.HasAttribute<ModuleAttribute>(false))
                       .Where(t => typeof(IModuleActivaor).IsAssignableFrom(t)
                           || typeof(IModuleListener).IsAssignableFrom(t)))
            {
                if (typeof(IModuleActivaor).IsAssignableFrom(t))
                    services.AddSingleton(typeof(IModuleActivaor), t);
                if (typeof(IModuleListener).IsAssignableFrom(t))
                    services.AddSingleton(typeof(IModuleListener), t);
            }

            return services;
        }

        /// <summary>
        /// 从Assembly 里注册Module 和 ModuleListener
        /// </summary>
        /// <returns></returns>
        public static IServiceRegistry AddModulesFromAssemblyOf<T>(this IServiceRegistry services)
        {
            Guard.NotNull(services, nameof(services));
            return AddModulesFromAssembly(services, typeof(T).Assembly);
        }
    }
}